using System;
using System.Linq;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Diagnostics;

namespace ImmediateWindow
{
	public enum DesignNotation
	{
		CSharp, VisualBasic, JavaScript, CPPCLI
	}
	public class CompilerKnobs
	{
		public CompilerKnobs(DesignNotation lang, int warnlevel, bool warnsAsErrs, string switches,ApplicationType apptype)
		{
			Language = lang;
			WarningLevel = warnlevel;
			WarningsAsErrors = warnsAsErrs;
			Switches = switches;
			AddedSwitches = string.Empty;
			ApplicationType = apptype;
		}
		public DesignNotation Language;
		public int WarningLevel;
		public bool WarningsAsErrors;
		public string Switches;
		public string AddedSwitches;
		public ApplicationType ApplicationType;

		public string GetAllCompilerSwitches()
		{
			string apptype="/target:"+ApplicationType.ToString()+" ";
			return apptype + Switches + AddedSwitches;
		}
	}

	interface IInputOutputForm
	{
		string[] GetSourceLines();
		object[] GetArguments();
		void WriteOutput(string text);
		void ClearOutput();
		List<string> References { get;set;}
		List<string> AvailableReferences { get;set;}
		CompilerKnobs CompilerOption { get;set;}
		Control[] GetFontControls();
	}

	class ActiveImmediate
	{
		string id;
		public ActiveImmediate(Form form)
		{
			id = DateTime.Now.ToLongTimeString();
			itsForm = form;
		}

		public Form itsForm;

		public override string ToString()
		{
			return id;
		}
	}

	public enum ApplicationType
	{
		exe,
		winexe,
		library,
		module
	}

	class WinFormRunner
	{
		Assembly exe;
		object[] args;
		public WinFormRunner(Assembly unit, object[] args) { exe = unit; this.args = args; }
		public void Invoke()
		{
			exe.EntryPoint.Invoke(null, args);
		}
	}

	class Utility
	{
		public static void AdjustSize(Form form)
		{
			if (form == null) return;
			form.Location = new Point(0, 0);
			MainForm parent = form.MdiParent as MainForm;
			form.Size = new Size(parent.Width - parent.CommonBarPanel.Width - 5, parent.Height - 5);
		}

		public static string NormalizeToFileName(string name)
		{
			string nospaces = name.Replace(' ', '-');
			return "GEN-"+nospaces.Replace(':', '-')+".EXE";
		}

    /*private static string GetWindowsSdkInstallationFolder()
    {
      //FrameworkSDKDir=C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0
      //SdkTools=C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin

      //program =  FrameworkSDKDir + "\\bin\\ildasm.exe"
      //program =  SdkTools + "\\ildasm.exe"

      string location = Environment.GetEnvironmentVariable("FrameworkSDKDir");
      if (string.IsNullOrEmpty(location))
        location = Environment.GetEnvironmentVariable("SdkTools");
      else
        location = location + "\\bin";
      if (!string.IsNullOrEmpty(location))
        location = location + "\\";
      return location;
    }*/

    private static string GetWindowsSdkInstallationFolder()
    {
      //HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows v6.0A v7.0A InstallationFolder
      using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows"))
      {
        if (key == null) throw new Exception("key null");
        string[] vers = key.GetSubKeyNames();
        if (vers.Length <= 0) throw new Exception("No Windows SDK versions found. I need ILDASM.EXE");
        Array.Sort(vers); // LINQ expr desc
        using (var fxver = key.OpenSubKey(vers[vers.Length - 1]))
        {
          object path = fxver.GetValue("InstallationFolder");
          if (path == null) throw new Exception("Windows SDK InstallationFolder is null. I need ILDASM.EXE");
          string InstallationFolder = System.IO.Path.Combine(path.ToString(), "bin");
          return InstallationFolder;
        }
      }
    }

		public static string Disassemble(string assembly_name)
		{
			string MSIL_lines=null;

			try
			{
        string location = GetWindowsSdkInstallationFolder();
        string ILDasm = Find(location, "ILDASM.EXE");// System.IO.Path.Combine(location, "ILDASM.EXE");
				using (Process ildasm = new Process())
				{
					ildasm.StartInfo.FileName = ILDasm;
					ildasm.StartInfo.Arguments = "/text " + assembly_name;
					ildasm.StartInfo.CreateNoWindow = true;
					ildasm.StartInfo.UseShellExecute = false;
					ildasm.StartInfo.RedirectStandardOutput = true;
					ildasm.Start();
					MSIL_lines=ildasm.StandardOutput.ReadToEnd();
					ildasm.WaitForExit();
				}
			}
			catch (Exception err)
			{
				MSIL_lines=err.Message;
			}
			return MSIL_lines;
		}

        private static string Find(string foldername, string file)
        {
            var result = Find(new System.IO.DirectoryInfo(foldername), file);
            if (result == null)
            {
                throw new Exception(string.Format("{0} not found in path hierarchy root {1}", file, foldername));
            }
            return result;
        }
        private static string Find(System.IO.DirectoryInfo folder, string file)
        {
            var target = folder.GetFiles(file).FirstOrDefault(f => string.Compare(f.Name, file, true) == 0);
            if (target != null)
            {
                return target.FullName;
            }
            else
            {
                string result = null;
                foreach (var subfolder in folder.GetDirectories())
                {
                    result = Find(subfolder, file);
                    if (result != null)
                    {
                        break;
                    }
                }
                return result;
            }
        }
	}
}
